using System;
using RabbitMQ.Client;
using RabbitMQ.Client.Exceptions;
using Wolfpack.Core;
using Wolfpack.Core.Checks;
using Wolfpack.Core.Interfaces.Entities;
using Wolfpack.Core.Notification;

namespace Wolfpack.Contrib.Checks.RabbitMQ
{
    public class RabbitQueueInfoCheck : ThresholdCheckBase<RabbitQueueInfoCheckConfig>
    {
        private readonly string _queueName;
        private ConnectionFactory _mqFactory;

        public RabbitQueueInfoCheck(RabbitQueueInfoCheckConfig config)
            : base(config)
        {
            _queueName = string.Format("{0}.{1}", config.Queue, config.HostName);
        }

        protected override PluginDescriptor BuildIdentity()
        {
            return new PluginDescriptor
            {
                Description = string.Format("Gathers information about the RabbitMQ queue '{0}'", _queueName),
                TypeId = new Guid("330EEAFF-A696-4BA0-8F2E-C004FFC672B1"),
                Name = _config.FriendlyId
            };
        }

        public override void Initialise()
        {
            _mqFactory = new ConnectionFactory
                             {
                                 HostName = _config.HostName,
                                 VirtualHost = _config.VirtualHost,
                                 Port = _config.Port,
                                 UserName = _config.Username,
                                 Password = _config.Password
                             };
        }

        public override void  Execute()
        {
            Publish(InspectQueue());
        }

        protected virtual NotificationRequest InspectQueue()
        {
            using (var mqConnection = _mqFactory.CreateConnection())
            {
                using (var mqModel = mqConnection.CreateModel())
                {
                    try
                    {
                        Logger.Debug("Checking length of rabbit queue '{0}'...", _queueName);
                        var mqQueue = mqModel.QueueDeclarePassive(_config.Queue);
                        var count = mqQueue.MessageCount;

                        var payload =
                            HealthCheckData.For(Identity, "RabbitMQ queue '{0}' has {1} messages", _queueName, count)
                                .AddProperty("Queue", _queueName)
                                .ResultCountIs(count)
                                .DisplayUnitIs(" mgs")
                                .Succeeded();

                        return NotificationRequestBuilder.For(_config.NotificationMode, payload).Build();
                    }
                    catch (OperationInterruptedException e)
                    {
                        var payload = HealthCheckData.For(Identity, "RabbitMQ queue '{0}' doesn't exist!", _queueName)
                            .AddProperty("Queue", _queueName)
                            .AddProperty("RabbitMQ_Message", e.Message)
                            .Failed();

                        return NotificationRequestBuilder.For(_config.NotificationMode, payload).Build();
                    }
                }
            }
        }
    }
}